#include "sfc/math/geo.h"
#include "sfc/test.h"

namespace sfc::math::geo {

SFC_TEST(vec_property) {
  auto v = Vec2d{};
  test::assert_eq(v[0], 0.0);
  test::assert_eq(v[1], 0.0);

  v = {1, 2};

  v = v.conj();
  test::assert_eq(v[0], +1.0);
  test::assert_eq(v[1], -2.0);

  auto p = Point::from_vec(v);
  test::assert_eq(v[0], p.x());
  test::assert_eq(v[1], p.y());
}

SFC_TEST(vec_direction) {
  const auto v0 = Vec2d{1, 0};
  test::assert_flt_eq(Angle{v0}.wrap_to_180(), 0);

  const auto v1 = Vec2d{1, 1};
  test::assert_flt_eq(Angle{v1}.wrap_to_180(), 45);

  const auto v2 = Vec2d{1, -1};
  test::assert_flt_eq(Angle{v2}.wrap_to_180(), -45);

  const auto v3 = Vec2d{-1, 1};
  test::assert_flt_eq(Angle{v3}.wrap_to_180(), 135);
}

SFC_TEST(vec_len) {
  const auto v0 = Vec2d{1, 0};
  const auto v1 = Vec2d{1, 1};

  test::assert_flt_eq(v0.length(), 1);
  test::assert_flt_eq(v0.length_sqr(), 1);

  test::assert_flt_eq(v1.length(), math::sqrt(2.0));
  test::assert_flt_eq(v1.length_sqr(), 2.0);
}

SFC_TEST(vec_unit) {
  const auto v0 = Vec2d{2, 0}.to_unit();
  const auto v1 = Vec2d{2, 2}.to_unit();

  test::assert_flt_eq(v0[0], 1.0);
  test::assert_flt_eq(v0[1], 0.0);

  test::assert_flt_eq(v1[0], 1.0 / math::sqrt(2.0));
  test::assert_flt_eq(v1[1], 1.0 / math::sqrt(2.0));
}

SFC_TEST(vec_norm) {
  const auto v0 = Vec2d{1, 0};
  const auto v1 = Vec2d{1, 1};

  test::assert_flt_eq(v0.norm1(), 1.0);
  test::assert_flt_eq(v1.norm1(), 2.0);

  test::assert_flt_eq(v0.norm2(), 1.0);
  test::assert_flt_eq(v1.norm2(), math::sqrt(2.0));
}

SFC_TEST(vec_prod) {
  const auto v0 = Vec2d{1, 0};
  const auto v1 = Vec2d{0, 1};

  const auto dot_prod = v0.dot_prod(v1);
  test::assert_flt_eq(dot_prod, 0);

  const auto cross_prod = v0.cross_prod(v1);
  test::assert_flt_eq(cross_prod, 1);
}

SFC_TEST(vec_ops) {
  const auto v0 = Vec2d{1, 0};
  const auto v1 = Vec2d{0, 1};

  const auto v2 = -v0;
  test::assert_flt_eq(v2[0], -1.0);
  test::assert_flt_eq(v2[1], +0.0);

  const auto v3 = v0 + v1;
  test::assert_flt_eq(v3[0], 1.0);
  test::assert_flt_eq(v3[1], 1.0);

  const auto v4 = v0 - v1;
  test::assert_flt_eq(v4[0], +1.0);
  test::assert_flt_eq(v4[1], -1.0);

  const auto v5 = 2 * v0;
  test::assert_flt_eq(v5[0], 2.0);
  test::assert_flt_eq(v5[1], 0.0);

  const auto v6 = v0 / 2;
  test::assert_flt_eq(v6[0], 0.5);
  test::assert_flt_eq(v6[1], 0.0);

  test::assert_flt_eq(v0.dot_prod(v0), 1.0);
  test::assert_flt_eq(v1.dot_prod(v1), 1.0);
  test::assert_flt_eq(v0.dot_prod(v1), 0.0);
}

}  // namespace sfc::math::geo
